package bakenote.ui;

import bakenote.BakeNote;
import bakenote.core.ElementalProcedure;
import bakenote.core.Procedure;
import bakenote.core.GetProcedureException;
import bakenote.core.Recipe;
import bakenote.xml.ProcedureXMLReader;
import org.apache.derby.iapi.services.io.LimitInputStream;
import org.apache.pivot.beans.BXML;
import org.apache.pivot.beans.Bindable;
import org.apache.pivot.collections.*;
import org.apache.pivot.collections.List;
import org.apache.pivot.util.Resources;
import org.apache.pivot.wtk.*;
import org.apache.pivot.wtk.Button;
import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.TextArea;

import javax.swing.text.TabableView;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.io.*;
import java.net.URL;
import java.util.StringTokenizer;

/**
 * User: lello
 * Date: 4/29/11
 * Time: 3:28 PM
 */
public class ProcedureEditorPane extends TablePane implements Bindable {

    @BXML
    PushButton addButton = null;
    @BXML
    PushButton removeButton = null;
    @BXML
    PushButton moveUpButton = null;
    @BXML
    PushButton moveDownButton = null;
    @BXML
    TablePane procedureTablePane = null;


    public ProcedureEditorPane() {
        // No-op
    }

    ButtonPressListener addButtonPressListener = new ButtonPressListener() {
        @Override
        public void buttonPressed(Button button) {
            // adding a new step
            TablePane.Row row = new TablePane.Row();
            row.setHeight("-1");
            TextArea descriptionTextArea = new TextArea();
            descriptionTextArea.setText("Add description here");
            TextArea timeTextArea = new TextArea();
            descriptionTextArea.getStyles().put("font", new Font("Verdana", Font.PLAIN, 12));
            timeTextArea.getStyles().put("font", new Font("Verdana", Font.PLAIN, 12));
            row.add(descriptionTextArea);
            row.add(timeTextArea);
            procedureTablePane.getRows().add(row);
        }
    };


    ButtonPressListener removeButtonPressListener = new ButtonPressListener() {
        @Override
        public void buttonPressed(Button button) {
            // We find the currently selected row, i.e. the row with the
            // TextArea currently being edited
            for (TablePane.Row row : procedureTablePane.getRows()) {
                boolean currentlySelected = ((TextArea) row.get(0)).isFocused() || ((TextArea) row.get(1)).isFocused();
                if (currentlySelected) {
                    procedureTablePane.getRows().remove(row);
                    break;
                }
            }
        }
    };

    ButtonPressListener moveUpButtonPressListener = new ButtonPressListener() {
        @Override
        public void buttonPressed(Button button) {
            // move the step upward
            for (TablePane.Row row : procedureTablePane.getRows()) {
                boolean currentlySelected = ((TextArea) row.get(0)).isFocused() || ((TextArea) row.get(1)).isFocused();
                if (currentlySelected) {
                    int irow = procedureTablePane.getRows().indexOf(row);
                    if (irow >= 1 && irow < procedureTablePane.getLength()) {
                        // swapt the rows
                        TablePane.Row t1Row = procedureTablePane.getRows().get(irow - 1);
                        TablePane.Row t2Row = procedureTablePane.getRows().get(irow);
                        procedureTablePane.getRows().remove(t1Row);
                        procedureTablePane.getRows().insert(t1Row, irow);
                        procedureTablePane.getRows().remove(t2Row);
                        procedureTablePane.getRows().insert(t2Row, irow - 1);
                    }
                    break;
                }
            }
        }
    };

    ButtonPressListener moveDownButtonPressListener = new ButtonPressListener() {
        @Override
        public void buttonPressed(Button button) {
            // move the step downward
            for (TablePane.Row row : procedureTablePane.getRows()) {
                boolean currentlySelected = ((TextArea) row.get(0)).isFocused() || ((TextArea) row.get(1)).isFocused();
                if (currentlySelected) {
                    // swap the rows
                    int irow = procedureTablePane.getRows().indexOf(row);
                    if (irow >= 0 && irow < procedureTablePane.getLength()) {
                        TablePane.Row t1Row = procedureTablePane.getRows().get(irow + 1);
                        TablePane.Row t2Row = procedureTablePane.getRows().get(irow);
                        procedureTablePane.getRows().remove(t1Row);
                        procedureTablePane.getRows().insert(t1Row, irow);
                        procedureTablePane.getRows().remove(t2Row);
                        procedureTablePane.getRows().insert(t2Row, irow + 1);
                    }
                    break;
                }
            }
        }
    };

    @Override
    public void initialize(Map<String, Object> stringObjectMap, URL url, Resources resources) {
        // No-op
        addButton.getButtonPressListeners().add(addButtonPressListener);
        removeButton.getButtonPressListeners().add(removeButtonPressListener);
        moveUpButton.getButtonPressListeners().add(moveUpButtonPressListener);
        moveDownButton.getButtonPressListeners().add(moveDownButtonPressListener);
    }

    /**
    private void openProcedureFile(File procedureFile) {
        if (procedureFile.exists()) {
            Procedure p = ProcedureXMLReader.readXML(procedureFile);
            // Show procedure in the tablePane
            for (int i = 0; i < p.getElementalProcedureList().getLength(); i++) {
                // description text area
                TextArea descriptionTextArea = new TextArea();
                descriptionTextArea.getStyles().put("font", new Font("Verdana", Font.PLAIN, 12));
                descriptionTextArea.setText(p.getStep(i).getDescription());
                // time text area
                TextArea timeTextArea = new TextArea();
                timeTextArea.getStyles().put("font", new Font("Verdana", Font.PLAIN, 12));
                int hours = p.getStep(i).getDuration().getHours();
                int minutes = p.getStep(i).getDuration().getMinutes();
                String hmTime = "";
                if (hours > 0) {
                    hmTime += String.valueOf(hours) + "h";
                }
                if (minutes > 0) {
                    hmTime += " " + String.valueOf(minutes) + "m";
                }
                timeTextArea.setText(hmTime.trim());
                TablePane.Row row = new TablePane.Row();
                row.add(descriptionTextArea);
                row.add(timeTextArea);
                procedureTablePane.getRows().add(row);
            }
        }
    }
    **/

    public void editProcedure(Recipe r) {
        if (r.getProcedure() != null) {
            Procedure p = r.getProcedure();
            // Show procedure in the tablePane
            for (int i = 0; i < p.getElementalProcedureList().getLength(); i++) {
                // description text area
                TextArea descriptionTextArea = new TextArea();
                descriptionTextArea.getStyles().put("font", new Font("Verdana", Font.PLAIN, 12));
                descriptionTextArea.setText(p.getStep(i).getDescription());
                // time text area
                TextArea timeTextArea = new TextArea();
                timeTextArea.getStyles().put("font", new Font("Verdana", Font.PLAIN, 12));
                int hours = p.getStep(i).getDuration().getHours();
                int minutes = p.getStep(i).getDuration().getMinutes();
                String hmTime = "";
                if (hours > 0) {
                    hmTime += String.valueOf(hours) + "h";
                }
                if (minutes > 0) {
                    hmTime += " " + String.valueOf(minutes) + "m";
                }
                timeTextArea.setText(hmTime.trim());
                TablePane.Row row = new TablePane.Row();
                row.add(descriptionTextArea);
                row.add(timeTextArea);
                procedureTablePane.getRows().add(row);
            }
        }
    }

    public Procedure getProcedure() throws GetProcedureException {
        Procedure procedure = null;
        if (procedureTablePane.getRows().getLength() > 0) {
            procedure = new Procedure();
            for (TablePane.Row row : procedureTablePane.getRows()) {
                String description = ((TextArea) row.get(0)).getText();
                String time = ((TextArea) row.get(1)).getText();
                if (validateTime(time)) {
                    ElementalProcedure elementalProcedure = new ElementalProcedure();
                    elementalProcedure.setDescription(description);
                    Duration duration = null;
                    String ptTime = "PT";
                    if (time.isEmpty()) {
                        ptTime += "0M";
                    } else {
                        time = time.toUpperCase();
                        ptTime += removeSpaces(time.trim());
                    }
                    try {
                        duration = DatatypeFactory.newInstance().newDuration(ptTime);
                    } catch (DatatypeConfigurationException e) {
                        e.printStackTrace();
                    }
                    elementalProcedure.setDuration(duration);
                    procedure.add(elementalProcedure);
                } else {
                    throw new GetProcedureException("Error in time format");
                }
            }
        }
        return procedure;
    }

    private boolean validateTime(String s) {
        String sTime = s.trim().toUpperCase();
        return sTime.matches("\\d*H\\s*\\d*M") || sTime.matches("\\d*H") || sTime.matches("\\d*M");
    }

    private String removeSpaces(String s) {
        StringTokenizer st = new StringTokenizer(s, " ", false);
        String t = "";
        while (st.hasMoreElements()) t += st.nextElement();
        return t;
    }

}
